/*******************************************************************************
 * Copyright (c) 2014. konbluesky  (blackjackhoho@gmail.com)
 * Lorem ipsum dolor sit amet, consectetur adipiscing elit.
 * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan.
 * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna.
 * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus.
 * Vestibulum commodo. Ut rhoncus gravida arcu.
 ******************************************************************************/

package com.fysports.web.model;

import com.google.common.base.Preconditions;
import com.jfinal.log.Log;
import com.jfinal.plugin.activerecord.*;
import com.jfinal.plugin.ehcache.CacheKit;
import com.fysports.framework.kit.sql.Conditions;
import com.fysports.web.kit.commons.DateTimeKit;
import com.fysports.web.kit.commons.StringKit;
import com.fysports.web.kit.commons.UUIDKit;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;


/**
 * Model 使用的基类
 * Created by konbluesky
 * Date : 14-7-1 下午1:53
 */
public abstract class BaseModel<M extends Model<M>> extends Model<M> {
    private static Log logger = Log.getLog(BaseModel.class);
    private static final TableMapping tableInfoMapping = TableMapping.me();
    private String tableName = tableInfoMapping.getTable(getClass()).getName();

    public static final String COL_LIVEFLAG = "liveflag";
    public static final String COL_UUID = "uuid";
    public static final String COL_CREATETIME = "createtime";


    /**
     * 生成UUID
     *
     * @return
     */
    public String generateUUID() {
        return UUIDKit.getUuidByJdk(true);
    }


    public String getUUID() {
        return this.getStr(COL_UUID);
    }


    private void checkTableName() {
        if (StringKit.isBlank(tableName))
            throw new IllegalArgumentException("tableName can not be blank,please setTableName(tableName)");
    }


    /**
     * 获取表映射对象
     *
     * @return
     */
    public Table getTable() {
        return tableInfoMapping.getTable(getClass());
    }


    public boolean save() {
        try {
            if (this.get(COL_CREATETIME) == null) {
                this.set(COL_CREATETIME, DateTimeKit.getDate());
            }
        }
        catch (Exception e) {
            logger.error("model save失败",e);
            throw new ActiveRecordException(e);
            //            this.set(COL_CREATETIME,DateTimeKit.getDate());
        }
        return super.save();
    }


    /**
     * 获取主键值
     *
     * @return
     */
    public String getPrimaryKeyValue() {
        return getTable().getPrimaryKey()[0];
    }


    /**
     * 获取首条记录
     *
     * @param key
     * @param value
     * @return
     */
    public M searchFirst(String key, Object value) {
        List<M> mList = search(key, value, "");
        return mList != null && mList.size() > 0 ? mList.get(0) : null;
    }


    /**
     * 获取List列表
     *
     * @param key
     * @param value
     * @return
     */
    public List<M> search(String key, Object value) {
        return search(key, value, "");
    }


    /**
     * 获取List列表(全部)
     *
     * @return
     */
    public List<M> searchAll() {
        return find("select * from " + tableName);
    }


    /**
     * 获取List列表（排序）
     *
     * @param key
     * @param value
     * @param orderBy
     * @return
     */
    public List<M> search(String key, Object value, String orderBy) {
        checkTableName();
        String sql = "select * from " + tableName + " where " + key + "=? " + orderBy;
        return find(sql, value);
    }


    /**
     * 多条件查询第一条记录
     *
     * @param maps
     * @return
     */
    public M searchFirst(Map<String, Object> maps) {
        List<M> mList = search(maps, "");
        return mList != null && mList.size() > 0 ? mList.get(0) : null;
    }


    public List<M> search(Map<String, Object> maps) {
        return search(maps, "");
    }


    public List<M> search(Map<String, Object> maps, String orderBy) {
        checkTableName();
        StringBuilder sb = new StringBuilder();
        sb.append("select * from ").append(tableName).append(" where 1=1 ");
        List<Object> values = new ArrayList<Object>();
        for (Map.Entry<String, Object> entry : maps.entrySet()) {
            if (entry.getValue() != null) {
                sb.append(" and ").append(entry.getKey()).append("=?");
                values.add(entry.getValue());
            }
        }
        sb.append(" ").append(orderBy);
        return find(sb.toString(), values.toArray());
    }


    public List<M> searchByCache(String cacheName, Object key, Map<String, Object> maps) {
        return this.searchByCache(cacheName, key, maps, "");
    }


    public List<M> searchByCache(String cacheName, Object key, Map<String, Object> maps, String orderBy) {
        checkTableName();
        List<M> result = CacheKit.get(cacheName, key);
        if (result == null) {
            result = search(maps);
            CacheKit.put(cacheName, key, result);
        }
        return result;
    }

    public Page<M> searchPaginate(int pageNumber, int pageSize, Map<String, Object> maps) {
        return this.searchPaginate(pageNumber, pageSize, maps,"createtime asc");
    }


    public Page<M> searchPaginate(int pageNumber, int pageSize, Map<String, Object> maps, String orderBy) {
        checkTableName();
        StringBuilder sb = new StringBuilder();
        sb.append(" from ").append(tableName).append(" where 1=1");
        List<Object> values = new ArrayList<Object>();
        //如不传参进来不生成条件sql
        if(maps!=null&&!maps.isEmpty()) {
            for (Map.Entry<String, Object> entry : maps.entrySet()) {
                if (entry.getValue() != null) {
                    sb.append(" and ").append(entry.getKey()).append("=?");
                    values.add(entry.getValue());
                }
            }
        }else{
            values=new ArrayList<Object>(0);
        }
        if (!StringKit.isBlank(orderBy)) {
            sb.append(" order by ").append(orderBy);
        }
        return paginate(pageNumber, pageSize, "select *", sb.toString(), values.toArray());
    }

    /**
     * DTGRID分页查找指定列数据
     * @param pageNumber
     * @param pageSize
     * @param selector
     * @param sqlExceptSelect
     * @param args
     * @return
     */
    public Page<M> DTSearchPaginate(int pageNumber, int pageSize, String selector,String sqlExceptSelect,String orderby,List<Object> args) {
        /* select选择器 */
        String _selector = selector;
        if (StringKit.isBlank(_selector)) {
            _selector = "select * ";
        }
        checkTableName();
        StringBuilder sb = new StringBuilder();
        if(!StringKit.isBlank(sqlExceptSelect)) {
            sb.append(sqlExceptSelect);
        }else {
            sb.append("from ").append(tableName).append(" where 1=1");
        }


        if(args==null || args.isEmpty()){
            args= new ArrayList<Object>(0);
        }

        if(StringKit.isBlank(orderby)){
            sb.append(" order by createtime asc");
        }
        return paginate(pageNumber, pageSize, _selector, sb.toString(), args.toArray());
    }


    /**
     * Conditions查询使用类
     *
     * @param pageNumber
     * @param pageSize
     * @param selector   优先顺序：condition.getSelector() -> selector -> "select *"
     * @param condition
     * @param orderby
     * @param rank
     * @return
     */
    public Page<M> searchPaginate(int pageNumber, int pageSize, String selector, Conditions condition,
            String orderby, String rank) {
        checkTableName();
        StringBuilder sb = new StringBuilder();
        sb.append("from ").append(tableName).append(" where 1=1 ");

        /* select选择器 */
        String _selector = "";

        if (StringKit.notBlank(condition.getSelector())) {
            _selector = condition.getSelector();
        }

        if (StringKit.notBlank(selector)) {
            _selector = condition.getSelector();
        }

        if (StringKit.isBlank(_selector)) {
            _selector = "select * ";
        }

        Object[] params = new Object[0];
        if (StringKit.notBlank(condition.getSql())) {
            sb.append(condition.getSql());
            if (condition.getParamList() != null) {
                params = condition.getParamList().toArray();
            }
        }
        /* 排序 */
        if (StringKit.notBlank(orderby)) {
            sb.append(" order by ").append(orderby).append(" ");
            if (StringKit.notBlank(rank)) {
                sb.append(rank);
            }
        }
        return paginate(pageNumber, pageSize, _selector, sb.toString(), params);
    }


    /**
     * Conditions查询使用类
     *
     * @param pageNumber
     * @param pageSize
     * @param condition
     * @param orderby
     * @param rank
     * @return
     */
    public Page<M> searchPaginate(int pageNumber, int pageSize, Conditions condition, String orderby,
            String rank) {
        return searchPaginate(pageNumber, pageSize, "select * ", condition, orderby, rank);
    }


    public Page<M> searchPaginateByCache(String cacheName, Object key, int pageNumber, int pageSize,
            Map<String, Object> maps) {
        return this.searchPaginateByCache(cacheName, key, pageNumber, pageSize, maps, "");
    }


    public Page<M> searchPaginateByCache(String cacheName, Object key, int pageNumber, int pageSize,
            Map<String, Object> maps, String orderBy) {
        checkTableName();
        Page<M> result = CacheKit.get(cacheName, key);
        if (result == null) {
            result = searchPaginate(pageNumber, pageSize, maps, orderBy);
            CacheKit.put(cacheName, key, result);
        }
        return result;
    }


    /**
     * ids数组转换成'xxx','xxx'
     * cc0bca8e490c406293d8d21dc5e7ac29,00b68fb624ae4fc8b15e7ad47795b7df
     * @param ids
     * @return
     */
    public String idsToString(String[] ids){
        StringBuilder sb=new StringBuilder();
        for(String s:ids){
            sb.append(",");
            sb.append("'");
            sb.append(s);
            sb.append("'");
        }
        return sb.substring(1).toString();
    }


    /**
     * 根据id1,id2,id3批量删除
     * @param ids
     * @return
     */
    public boolean deletebatch(String ids){
        Preconditions.checkNotNull(ids);
        String[] sid=ids.split(",");
        String sql="delete from "+ getTable().getName() + " where uuid in ("+idsToString(sid)+")";
        return Db.update(sql)==sid.length;
    }
}
